package ink.metoo.gude.handler

import ink.metoo.gude.GudeServerApplication
import ink.metoo.gude.model.ApiBody
import ink.metoo.gude.model.ApiStatus
import ink.metoo.gude.util.ApiUtils
import org.springframework.context.MessageSource
import org.springframework.web.bind.MethodArgumentNotValidException
import org.springframework.web.bind.annotation.ExceptionHandler
import org.springframework.web.bind.annotation.RestControllerAdvice
import java.util.*

@RestControllerAdvice(
    basePackages = [
        GlobalExceptionHandler.CONTROLLER_SCAN_BASE_PACKAGE,
    ]
)
class GlobalExceptionHandler(private val messageSource: MessageSource) {

    @ExceptionHandler(exception = [ApiException::class])
    fun handleApiException(e: ApiException): ApiBody<Any> = ApiUtils.createBody(e.apiStatus, e.record)

    @ExceptionHandler(exception = [MethodArgumentNotValidException::class])
    fun handleMethodArgumentNotValidException(e: MethodArgumentNotValidException, locale: Locale): ApiBody<Any> {
        val errors = e.bindingResult.fieldErrors.associate { fieldError ->
            val message = messageSource.getMessage(fieldError, locale)
            fieldError.field to message
        }
        return ApiUtils.createBody(ApiStatus.U_2004, errors)
    }

    companion object {
        const val CONTROLLER_SCAN_BASE_PACKAGE =
            "${GudeServerApplication.BASE_PACKAGE}.module"
    }
}